package com.mingren.manager.auth;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.mingren.exception.BusinessException;
import com.mingren.exception.ErrorCode;
import com.mingren.manager.auth.model.SpaceUserAuthConfig;
import com.mingren.manager.auth.model.SpaceUserRole;
import com.mingren.model.domain.Space;
import com.mingren.model.domain.SpaceUser;
import com.mingren.model.domain.User;
import com.mingren.model.enums.SpaceRoleEnum;
import com.mingren.model.enums.SpaceTypeEnum;
import com.mingren.service.SpaceService;
import com.mingren.service.SpaceUserService;
import com.mingren.service.UserService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 曹宏福
 * @version 1.0
 * 空间成员权限管理类
 */
@Component
public class SpaceUserAuthManager {

    @Resource
    private UserService userService;

    @Resource
    private SpaceUserService spaceUserService;

    @Resource
    private SpaceService spaceService;
    /**
     * 空间用户权限常量类
     */
    public static final SpaceUserAuthConfig SPACE_USER_AUTH_CONFIG;

    /**
     * 静态代码块初始化上面的常量类
     */
    static {
        //读取配置文件->得到json数据
        String json = ResourceUtil.readUtf8Str("biz/spaceUserAuthConfig.json");
        //将json数据解析
        SPACE_USER_AUTH_CONFIG = JSONUtil.toBean(json, SpaceUserAuthConfig.class);
    }

    /**
     * 公共方法->根据角色获取权限列表
     */
    public List<String> getPermissionsByRole(String spaceUserRole) {
        //如果角色为空 也就没有权限
        if (StrUtil.isBlank(spaceUserRole)) {
            return new ArrayList<>();
        }
        //获取所有的角色列表 根据流式计算匹配
        List<SpaceUserRole> roles = SPACE_USER_AUTH_CONFIG.getRoles();
        //获取角色信息
        SpaceUserRole role = roles.stream().filter(item -> {
            return spaceUserRole.equals(item.getKey());
        }).findFirst().orElse(null); //用于从流中获取第一个元素 如果没找到则返回空
        //获取权限
        if (role == null) {
            return new ArrayList<>();
        }
        return role.getPermissions();
    }

    /**
     * 获取登录用户的权限列表,返回给前端展示
     *
     * @param space:传入空间
     * @param loginUser:登录用户
     * @return
     */
    public List<String> getPermissionList(Space space, User loginUser) {
        //获取空间权限列表为备用
        List<String> ADMIN_PERMISSIONS = getPermissionsByRole(SpaceRoleEnum.ADMIN.getValue());
        //如果当前登录用户为空,就没有获取空间的权限
        if (loginUser == null) {
            return new ArrayList<>();
        }
        //如果已经登录用户 分析当前用户请求的是公共/私有/团队
        //1、请求的是公共图库 space == null? 为什么 为空就是公共图库？->
        if (space == null) {
            //请求的是公共图库 给管理员权限
            //如果当前登录用户是管理员,直接赋予管理员权限
            if (userService.isAdmin(loginUser)) {
                return ADMIN_PERMISSIONS;
            }
            //如果是普通用户返回空的权限列表
            return new ArrayList<>();
        }
        //获取请求空间的类型
        Integer spaceType = space.getSpaceType();
        //获取空间类型枚举类
        SpaceTypeEnum enumByValue = SpaceTypeEnum.getEnumByValue(spaceType);
        if (enumByValue == null) {
            //判空
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间类型不存在");
        }
        //根据空间类型和用户权限 返回对应的权限列表
        switch (enumByValue) {
            case TEAM:
                //如果请求的是团队空间->查询对应的成员空间列表
                SpaceUser spaceUser = spaceUserService.lambdaQuery()
                        .eq(SpaceUser::getUserId, loginUser.getId())
                        .eq(SpaceUser::getSpaceId, space.getId())
                        .one();
                //判空
                if (spaceUser == null) {
                    throw new BusinessException(ErrorCode.NULL_ERROR, "空间成员为空");
                }
                //如果不为空,返回对应的成员权限列表
                return getPermissionsByRole(spaceUser.getSpaceRole());
            case PRIVATE:
                //如果请求的是私有空间->不需要查询空间成员列表只需要判断该用户是否是传入空间本人或者管理员
                spaceService.checkSpaceAuth(loginUser, space);
                //通过则返回管理员权限
                return ADMIN_PERMISSIONS;
            default:
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "请求空间类别不存在");
        }
    }

}
